From 5cf2bea385d1bdd409f06789220910876c0ab17d Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Thu, 19 Sep 2013 15:33:59 +0200 Subject: [PATCH] libxl: add Qdisk backend launch helper MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Current Qemu launch functions in libxl require the usage of data structures only avaialbe on domain creation. All this information is not need in order to launch a Qemu instance to serve Qdisk backends, so introduce a new simplified helper that can be used to launch Qemu/Qdisk, that will be used to launch Qdisk in driver domains. Signed-off-by: Roger Pau Monné Cc: Ian Campbell Cc: Anthony PERARD Cc: Stefano Stabellini Acked-by: Ian Jackson --- tools/libxl/libxl_dm.c | 148 +++++++++++++++++++++++++++++++---- tools/libxl/libxl_internal.h | 6 ++ 2 files changed, 138 insertions(+), 16 deletions(-) diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index b4798b870d..292e351787 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -42,6 +42,23 @@ static const char *qemu_xen_path(libxl__gc *gc) #endif } +static int libxl__create_qemu_logfile(libxl__gc *gc, char *name) +{ + char *logfile; + int logfile_w; + + libxl_create_logfile(CTX, name, &logfile); + logfile_w = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644); + free(logfile); + + if (logfile_w < 0) { + LOGE(ERROR, "unable to open Qemu logfile"); + return ERROR_FAIL; + } + + return logfile_w; +} + const char *libxl__domain_device_model(libxl__gc *gc, const libxl_domain_build_info *info) { @@ -1149,7 +1166,7 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) const libxl_domain_create_info *c_info = &guest_config->c_info; const libxl_domain_build_info *b_info = &guest_config->b_info; const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config); - char *path, *logfile; + char *path; int logfile_w, null; int rc; char **args, **arg; @@ -1204,11 +1221,12 @@ void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss) libxl__xs_write(gc, XBT_NULL, libxl__sprintf(gc, "%s/disable_pf", path), "%d", !libxl_defbool_val(b_info->u.hvm.xen_platform_pci)); - libxl_create_logfile(ctx, - libxl__sprintf(gc, "qemu-dm-%s", c_info->name), - &logfile); - logfile_w = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644); - free(logfile); + logfile_w = libxl__create_qemu_logfile(gc, GCSPRINTF("qemu-dm-%s", + c_info->name)); + if (logfile_w < 0) { + rc = logfile_w; + goto out; + } null = open("/dev/null", O_RDONLY); const char *dom_path = libxl__xs_get_dompath(gc, domid); @@ -1268,7 +1286,6 @@ out: static void device_model_confirm(libxl__egc *egc, libxl__spawn_state *spawn, const char *xsdata) { - libxl__dm_spawn_state *dmss = CONTAINER_OF(spawn, *dmss, spawn); STATE_AO_GC(spawn->ao); if (!xsdata) @@ -1320,18 +1337,91 @@ static void device_model_spawn_outcome(libxl__egc *egc, dmss->callback(egc, dmss, rc); } -int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid) +void libxl__spawn_qdisk_backend(libxl__egc *egc, libxl__dm_spawn_state *dmss) { - char *pid; - int ret; + STATE_AO_GC(dmss->spawn.ao); + flexarray_t *dm_args; + char **args; + const char *dm; + int logfile_w, null, rc; + uint32_t domid = dmss->guest_domid; + + /* Always use qemu-xen as device model */ + dm = qemu_xen_path(gc); + + dm_args = flexarray_make(gc, 15, 1); + flexarray_vappend(dm_args, dm, "-xen-domid", + GCSPRINTF("%d", domid), NULL); + flexarray_append(dm_args, "-xen-attach"); + flexarray_vappend(dm_args, "-name", + GCSPRINTF("domain-%u", domid), NULL); + flexarray_append(dm_args, "-nographic"); + flexarray_vappend(dm_args, "-M", "xenpv", NULL); + flexarray_vappend(dm_args, "-monitor", "/dev/null", NULL); + flexarray_vappend(dm_args, "-serial", "/dev/null", NULL); + flexarray_vappend(dm_args, "-parallel", "/dev/null", NULL); + flexarray_append(dm_args, NULL); + args = (char **) flexarray_contents(dm_args); - pid = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/image/device-model-pid", domid)); - if (!pid || !atoi(pid)) { - LOG(ERROR, "could not find device-model's pid for dom %u", domid); - ret = ERROR_FAIL; + logfile_w = libxl__create_qemu_logfile(gc, GCSPRINTF("qdisk-%u", domid)); + if (logfile_w < 0) { + rc = logfile_w; + goto error; + } + null = open("/dev/null", O_RDONLY); + + dmss->guest_config = NULL; + /* + * Clearly specify Qemu not using a saved state, so + * device_model_spawn_outcome doesn't try to unlink it. + */ + dmss->build_state = libxl__zalloc(gc, sizeof(*dmss->build_state)); + dmss->build_state->saved_state = 0; + + dmss->spawn.what = GCSPRINTF("domain %u Qdisk backend", domid); + dmss->spawn.xspath = GCSPRINTF("device-model/%u/state", domid); + dmss->spawn.timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000; + /* + * We cannot save Qemu pid anywhere in the xenstore guest dir, + * because we will call this from unprivileged driver domains, + * so save it in the current domain libxl private dir. + */ + dmss->spawn.pidpath = GCSPRINTF("libxl/%u/qdisk-backend-pid", domid); + dmss->spawn.midproc_cb = libxl__spawn_record_pid; + dmss->spawn.confirm_cb = device_model_confirm; + dmss->spawn.failure_cb = device_model_startup_failed; + dmss->spawn.detached_cb = device_model_detached; + rc = libxl__spawn_spawn(egc, &dmss->spawn); + if (rc < 0) + goto error; + if (!rc) { /* inner child */ + setsid(); + libxl__exec(gc, null, logfile_w, logfile_w, dm, args, NULL); + } + + return; + +error: + assert(rc); + dmss->callback(egc, dmss, rc); + return; +} + +/* Generic function to signal a Qemu instance to exit */ +static int kill_device_model(libxl__gc *gc, const char *xs_path_pid) +{ + const char *xs_pid; + int ret, pid; + + ret = libxl__xs_read_checked(gc, XBT_NULL, xs_path_pid, &xs_pid); + if (ret || !xs_pid) { + LOG(ERROR, "unable to find device model pid in %s", xs_path_pid); + ret = ret ? : ERROR_FAIL; goto out; } - ret = kill(atoi(pid), SIGHUP); + pid = atoi(xs_pid); + + ret = kill(pid, SIGHUP); if (ret < 0 && errno == ESRCH) { LOG(ERROR, "Device Model already exited"); ret = 0; @@ -1339,7 +1429,7 @@ int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid) LOG(DEBUG, "Device Model signaled"); ret = 0; } else { - LOGE(ERROR, "failed to kill Device Model [%d]", atoi(pid)); + LOGE(ERROR, "failed to kill Device Model [%d]", pid); ret = ERROR_FAIL; goto out; } @@ -1348,6 +1438,32 @@ out: return ret; } +/* Helper to destroy a Qdisk backend */ +int libxl__destroy_qdisk_backend(libxl__gc *gc, uint32_t domid) +{ + char *pid_path; + int rc; + + pid_path = GCSPRINTF("libxl/%u/qdisk-backend-pid", domid); + + rc = kill_device_model(gc, pid_path); + if (rc) + goto out; + + libxl__xs_rm_checked(gc, XBT_NULL, pid_path); + libxl__xs_rm_checked(gc, XBT_NULL, + GCSPRINTF("device-model/%u", domid)); + +out: + return rc; +} + +int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid) +{ + return kill_device_model(gc, + GCSPRINTF("/local/domain/%d/image/device-model-pid", domid)); +} + int libxl__need_xenpv_qemu(libxl__gc *gc, int nr_consoles, libxl__device_console *consoles, int nr_vfbs, libxl_device_vfb *vfbs, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index e3b9fb4581..cff35183f3 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -2548,6 +2548,12 @@ _hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*); _hidden char *libxl__stub_dm_name(libxl__gc *gc, const char * guest_name); +/* Qdisk backend launch helpers */ + +_hidden void libxl__spawn_qdisk_backend(libxl__egc *egc, + libxl__dm_spawn_state *dmss); +_hidden int libxl__destroy_qdisk_backend(libxl__gc *gc, uint32_t domid); + /*----- Domain creation -----*/ typedef struct libxl__domain_create_state libxl__domain_create_state; -- 2.30.2